package com.stegniy.singlyLinkedList;

import java.util.*;

public class SinglyLinkedList<T> implements Iterable<T> {
    private Node<T> head;

    public SinglyLinkedList() {
        head = null;
    }

    public void add(T element) {
        head = new Node<T>(element, head);
    }

    public boolean contains(T element) {
        for (T elements : this)
            if (elements.equals(element))
                return true;
        return false;
    }

    public int size() {
        int size = 0;
        for (T elements : this)
            size++;
        return size;
    }

    public void removeAll() {
        Node<T> current = head;
        while (current != null) {
            current.data = null;
            current = current.next;
        }
        head = null;
    }

    public void remove(T element) {
        if(head == null)
            throw new NoSuchElementException("List is empty");

        if(head.data.equals(element)) {
            head = head.next;
            return;
        }

        Node<T> current  = head;
        Node<T> prev = null;

        while((current != null) && (!current.data.equals(element))) {
            prev = current;
            current = current.next;
        }

        if(current == null)
            throw new NoSuchElementException("Element not exist");

        //delete current node
        prev.next = current.next;
    }

    private static class Node<T> {
        T data;
        Node<T> next;

        Node(T data, Node<T> next) {
            this.data = data;
            this.next = next;
        }
    }

    public Iterator<T> iterator() {
        return new SLLIterator();
    }

    private class SLLIterator implements Iterator<T> {
        private Node<T> nextNode;

        public SLLIterator() {
            nextNode = head;
        }

        public boolean hasNext() {
            return nextNode != null;
        }

        public T next() {
            if (hasNext()) {
                T result = nextNode.data;
                nextNode = nextNode.next;
                return result;
            } else {
                throw new NoSuchElementException();
            }
        }

        public void remove() {
            throw new UnsupportedOperationException();
        }
    }

    public String toString() {
        StringBuffer result = new StringBuffer();
        for(Object x : this)
            result.append(x + " ");

        return result.toString();
    }
}

